#define _GNU_SOURCE
#define MAX 1000

#include "../include/client.h"

int sendFile(int sockFd, const char *md5str)
{
    //服务器上的文件是以MD5码命名的
    //采用“零拷贝”的方式根据请求发送不定长的文件
    Train_t train;
    char flag;
    int dataLen = 0;
    int pos = 0;    //续传时要偏移的量
    
    //先发送文件名
    /* train.dataLen = strlen(fileName); */
    /* memcpy(train.buf, fileName, train.dataLen); */
    /* send(sockFd, &train, 4 + train.dataLen, 0);    // 把文件名发过去 */

    
    //打开文件，读取并发送
    int fd = open(md5str, O_RDWR);
    ERROR_CHECK(fd, -1, "open");

    //获取文件大小，并发送给客户端
    struct stat fileInfo;
    fstat(fd, &fileInfo);
    int fileSize = (int)fileInfo.st_size;

    // 1、发送文件的大小
    memset(&train, 0, sizeof(train));
    train.dataLen = 4;
    memcpy(train.buf, &fileSize, train.dataLen);
    send(sockFd, &train, 4+train.dataLen, 0);

    // 2、发送文件的MD5码
    memset(&train, 0, sizeof(train));
    train.dataLen = strlen(md5str);
    memcpy(train.buf, md5str, train.dataLen);
    send(sockFd, &train, 4+train.dataLen, 0);

    // 3、接收是否要传输文件的信号
    recv(sockFd, &flag, 1, 0);
    if(flag == 'q'){
        //本地已经存在了，不用下载
        return 1;
    }

    // 4、接收客户端发回的偏移指针，从偏移后的地方开始读取并发送
    recv(sockFd, &dataLen, 4, 0);
    recv(sockFd, &pos, dataLen, 0);
    lseek(fd, pos, SEEK_SET);  //偏移文件的指针

    // 5、开始发送文件
    int fdPipe[2];
    pipe(fdPipe);
    int sendRet = 0;
    int sendSize = pos;

    while(sendSize < fileInfo.st_size){
        //循环从文件中读出，然后通过管道发送个客户端
        sendRet = splice(fd, 0, fdPipe[1], 0, MAX, 0);
        sendRet = splice(fdPipe[0], 0, sockFd, 0, MAX, 0);
        if(-1 == sendRet){
            //连接断了，直接返回！
            printf("client exit!\n");
            /* break; */
            close(fd);
            close(fdPipe[0]);
            close(fdPipe[1]);
            return -1;
        }
        sendSize += sendRet;
    }
    close(fd);
    close(fdPipe[0]);
    close(fdPipe[1]);

    return 1;
}

